#encoding:utf8

"""
GENEERAL LOGGING FRAMEWORK
主要解决同一个项目中, 不同的配置需要不同的文件路径, 而采用配置文件方式无法解决

USAGE:
for examples:
    logger = get_logger(name, handlers=['simple'], path, filename, formatter, **kwargs)
    logger.info("info")
    logger.warn("warn")
    logger.critical("critical")

parameters ::
    name :: string. the name of logger
    handlers :: list of string. values: console, rfile, rtfile
    path :: string. the logging path
    filename :: string. logging filename
    formatter :: string. empty, simple, info, detail

kwargs ::
    backupCount :: for rfile, rtfile
    interval :: for rtfile
    when :: for rtfile
    maxBytes :: for rfile
"""


import os
import logging
from logging.handlers import RotatingFileHandler
from logging.handlers import TimedRotatingFileHandler


HANDLER_NAMES = set()  # must be 'console', 'rfile', 'rtfile'
HANDLER_DICT = {}


def get_logger(name, handlers=['console'], path="./", filename="run.log", formatter="simple", **kwargs):
    backupCount = kwargs.get("backupCount", 30)
    interval = kwargs.get("interval", 1)
    when = kwargs.get("when", "midnight")
    maxBytes = kwargs.get("maxBytes", 10 * 1024 * 1024)
    level = kwargs.get("level", 'info')
    level = LEVEL_DICT[level]

    formatter = FORMATER_DICT.get(formatter, FORMATER_SIMPLE)
    if not os.path.exists(path):
        os.makedirs(path)
    log_path = os.path.join(path, filename)

    logger = logging.getLogger(name)
    logger.setLevel(level)
    for handler in handlers:
        assert handler in HANDLER_DICT, \
            "logger name[%s] must be one of [%s]" % (handler, ','.join(HANDLER_NAMES))
        handler = HANDLER_DICT[handler](formatter=formatter, log_path=log_path, level=level,
                                        backupCount=backupCount,
                                        interval=interval,
                                        when=when,
                                        maxBytes=maxBytes,
                                        )
        logger.addHandler(handler)
    return logger


# default formatters
FORMATER_EMPTY = ""  # used to simply print log info
FORMATER_SIMPLE = "%(asctime)s-%(name)s-%(levelname)s:: %(message)s"
FORMATER_INFO = "%(levelname)-8s %(name)s[%(filename)s: %(lineno)3d]:: %(message)s"
FORMATER_DETAIL = "%(asctime)s %(levelname)-8s %(name)s[%(filename)s: %(lineno)3d]:: %(message)s"

FORMATER_DICT = {
    "empty": FORMATER_EMPTY,
    "simple": FORMATER_SIMPLE,
    "info": FORMATER_INFO,
    "detail": FORMATER_DETAIL
}

LEVEL_DICT = {
    'debug': logging.DEBUG,
    'info': logging.INFO,
    'warn': logging.WARN,
    'error': logging.ERROR,
    'critical': logging.CRITICAL
}


def get_console_handler(formatter=FORMATER_SIMPLE, **kwargs):
    ch = logging.StreamHandler()
    ch.setLevel(logging.INFO)
    formatter = logging.Formatter(formatter)
    ch.setFormatter(formatter)
    return ch
HANDLER_NAMES.add("console")
HANDLER_DICT['console'] = get_console_handler


def get_rfile_handler(formatter=FORMATER_SIMPLE, **kwargs):
    log_path = kwargs.get("log_path", "./run.log")
    backupCount = kwargs.get("backupCount", 30)
    maxBytes = kwargs.get("maxBytes", 10*1024*1024)

    Rthandler = RotatingFileHandler(log_path, maxBytes=maxBytes, backupCount=backupCount)
    Rthandler.setLevel(logging.INFO)
    formatter = logging.Formatter(formatter)
    Rthandler.setFormatter(formatter)
    return Rthandler
HANDLER_NAMES.add("rfile")
HANDLER_DICT['rfile'] = get_rfile_handler


def get_rtfile_handler(formatter=FORMATER_SIMPLE, **kwargs):
    log_path = kwargs.get("log_path", "./run.log")
    backupCount = kwargs.get("backupCount", 30)
    interval = kwargs.get("interval", 1)
    when = kwargs.get("when", "midnight")

    Rthandler = TimedRotatingFileHandler(log_path, when=when, interval=interval, backupCount=backupCount)
    Rthandler.setLevel(logging.INFO)
    formatter = logging.Formatter(formatter)
    Rthandler.setFormatter(formatter)
    return Rthandler
HANDLER_NAMES.add("rtfile")
HANDLER_DICT['rtfile'] = get_rtfile_handler


def test_get_logger():
    name = "test"
    handlers = ['console', 'rtfile']
    formatter = "detail"
    path = "./log/"

    logger = get_logger(name, handlers=handlers, formatter=formatter, path=path, level="error")
    logger.info('this is a new world')
    logger.error("error happens here")


if __name__ == "__main__":
    test_get_logger()

